package com.nsb.ihguapp.module;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class NetworkModule extends ReactContextBaseJavaModule {

    /**
     * ping头部默认大小（byte）
     */
    private final Integer PING_PACKAGE_DEFAULT_SIZE = 8;

    /**
     * 发送数据包大小
     */
    private final Integer PING_PACKAGE_SIZE = 24;

    /**
     * ping默认次数
     */
    private final Integer PING_DEFAULT_SECONDS = 3;

    public NetworkModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "NetworkUtils";
    }

    /**
     * ping方法
     * @param host 目标主机ip或者域名
     * @param promise
     */
    @ReactMethod
    public void ping(String host, Promise promise) {

        WritableMap map = Arguments.createMap();
        Process process = null;
        BufferedReader sb = null;

        try {

            String line = null;
            StringBuffer resultStringBuffer = new StringBuffer();
            StringBuffer commandStr = new StringBuffer("ping").append(" ").
                    append("-c").append(PING_DEFAULT_SECONDS).append(" -w3").
                    append(" -s").append(PING_PACKAGE_SIZE).append(" ").append(host);

            process = Runtime.getRuntime().exec(commandStr.toString());
            sb = new BufferedReader(new InputStreamReader(process.getInputStream()));

            while ((line = sb.readLine()) != null) {
                if (line.contains(String.valueOf(PING_PACKAGE_SIZE + PING_PACKAGE_DEFAULT_SIZE))) {
                    resultStringBuffer.append(line + "\r\n");
                }
            }
            int status = process.waitFor();

            map = process.waitFor() == 0 ? returnMap(true, resultStringBuffer.toString(), getAverageValue(resultStringBuffer.toString(), PING_DEFAULT_SECONDS)) :
                    returnMap(false, getStringFromInputStream(process.getErrorStream()).toString(), null);

        } catch (Exception e) {
            e.printStackTrace();
            map = returnMap(false, e.getMessage(), null);
        } finally {
            if (process != null) {
                process.destroy();
            }
            if (sb != null) {
                try {
                    sb.close();
                } catch (IOException ioe) {
                }
            }
            promise.resolve(map);
        }
    }

    /**
     * 计算平均值
     * @param data
     * @param number
     * @return
     */
    private WritableMap getAverageValue(String data, Integer number) {
        String[] ss = data.split("=");
        WritableMap map = Arguments.createMap();
        float f = 0;
        float result = 0;
        float srate = 0;
        for (int x = 3; x < ss.length; x += 3) {
            f += Float.parseFloat(ss[x].substring(0, ss[x].indexOf("m")));
        }

        if (number != 0) {
            result = f / number;
            srate = number / 3;
            map.putDouble("srate", srate);
            map.putDouble("avg", result);
        }

        return map;
    }

    /**
     * 将InputStream包装成StringBuffer
     * @param inputStream
     * @return
     * @throws Exception
     */
    private StringBuffer getStringFromInputStream(InputStream inputStream) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer resultStringBuffer = new StringBuffer();
        String line = null;

        while ((line = reader.readLine()) != null) {
            resultStringBuffer.append(line);
            resultStringBuffer.append("\n");
        }

        return resultStringBuffer;
    }

    /**
     * 返回信息
     * @param isSuccess 是否成功
     * @param message   提示信息
     * @param result    所需信息
     * @return
     */
    private WritableMap returnMap(Boolean isSuccess, String message, WritableMap result) {
        WritableMap map = Arguments.createMap();
        map.putBoolean("isSuccess", isSuccess);
        map.putString("message", null != message ? message : "");
        map.putMap("result", result);

        return map;
    }
}
